package org.hsieh.tr.explore.db;

import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Date;

import org.hsieh.tr.explore.exception.SqlCommandExecuteException;
import org.hsieh.tr.explore.ui.SQLCommandManager;

public class SqlCommand implements ISqlCommand, Comparable<ISqlCommand> {

	public SqlCommand() {

	}

	private SqlCommand(final String sql) {
		this.sqlExpression = sql;
	}

	public static SqlCommand create(final String sql) {
		SqlCommand command = new SqlCommand(sql);
		return command;
	}

	private String sqlExpression;

	private long executeTime;

	private Connection connection;

	public Connection getConnection() {
		return connection;
	}

	public void setExecuteTime(long executeTime) {
		this.executeTime = executeTime;
	}

	private int isolcationLevelWhenExecute;

	public int getIsolcationLevelWhenExecute() {
		return isolcationLevelWhenExecute;
	}

	public void setIsolcationLevelWhenExecute(int isolcationLevelWhenExecute) {
		this.isolcationLevelWhenExecute = isolcationLevelWhenExecute;
	}

	public String getSqlExpression() {
		return sqlExpression;
	}

	public void setSqlExpression(String sqlExpression) {
		this.sqlExpression = sqlExpression;
	}

	public Object execute(final Connection connection)
			throws SqlCommandExecuteException {
		executeTime = System.currentTimeMillis();
		try {
			setIsolcationLevelWhenExecute(connection.getTransactionIsolation());
			this.connection = connection;
			Object result = null;
			Statement statement = connection.createStatement();
			if (isSelect()) {
				result = statement.executeQuery(getSqlExpression());
			} else if (isUpdate()) {
				result = statement.executeUpdate(getSqlExpression());
			} else {
				result = statement.execute(getSqlExpression());
			}
			// Only record success command
			SQLCommandManager.getInstance().addCommands(this);
			return result;
		} catch (SQLException e) {
			throw new SqlCommandExecuteException(getSqlExpression(), e);
		}
	}

	protected boolean isSelect() {
		return getSqlExpression().trim().toUpperCase().startsWith("SELECT");
	}

	protected boolean isUpdate() {
		return getSqlExpression().trim().toUpperCase().startsWith("UPDATE")
				|| getSqlExpression().trim().toUpperCase().startsWith("DELETE")
				|| getSqlExpression().trim().toUpperCase().startsWith("INSERT");
	}

	public long getExecuteTime() {
		return executeTime;
	}

	public int compareTo(ISqlCommand o) {
		Date old = new Date(o.getExecuteTime());
		Date now = new Date(getExecuteTime());
		return old.before(now) ? -1 : 1;
	}

}
